package moonshine
{
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.sampler.startSampling;
	import flash.ui.Keyboard;
	
	public class SelectionManager
	{
		public var editor:TextEditor;
		public var model:TextEditorModel;

		public function handleMouseDown(event:MouseEvent):void
		{
			var rdr:TextLineRenderer = getRendererAtPoint(event.stageX, event.stageY);
			if (!rdr) return;
			
			var newLineSelection:int = rdr.dataIndex;
			if (newLineSelection != model.selectedLineIndex && newLineSelection != -1)
			{
				var oldRenderer:TextLineRenderer = editor.getRendererFromIndex(model.selectedLineIndex);
				if (oldRenderer) oldRenderer.focus = false;
				rdr.focus = true;
			}
			
			model.selectedLineIndex = newLineSelection;
			model.caretIndex = rdr.getCharIndexFromPoint(event.stageX, event.stageY);;
			
			model.selectionStartLineIndex = model.selectedLineIndex;
			model.selectionStartCharIndex = -1;

			
			editor.invalidateSelection();
			
			editor.itemContainer.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
		}
		
		public function handleMouseUp(event:MouseEvent):void
		{
			editor.itemContainer.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
			if (!model.hasSelection) model.selectionStartLineIndex = -1;
		}
		
		public function handleMouseMove(event:MouseEvent):void
		{
			var rdr:TextLineRenderer = getRendererAtPoint(event.stageX, event.stageY);
			if (!rdr) return;
			
			var newCaretPosition:int = rdr.getCharIndexFromPoint(event.stageX, event.stageY);
			if (newCaretPosition == -1) return;
			
			if (model.selectionStartCharIndex == -1)
			{
				model.selectionStartCharIndex = model.caretIndex;
			}
			
			model.caretIndex = newCaretPosition;
			model.selectedLineIndex = rdr.dataIndex;
			
			editor.invalidateSelection();
		}
		
		public function handleKeyDown(event:KeyboardEvent):void
		{
			switch (event.keyCode)
			{
				case Keyboard.LEFT:
				{
					if (model.hasSelection)
					{
						if (model.selectedLineIndex > model.selectionStartLineIndex)
						{
							model.caretIndex = model.selectionStartCharIndex;
							model.selectedLineIndex = model.selectionStartLineIndex;
						}
						removeSelection();					
					}
					else if (model.caretIndex > 0)
					{
						model.caretIndex--;
					}
					else
					{
						if (model.selectedLineIndex == 0) return;
						
						model.selectedLineIndex--;
						model.caretIndex = model.lines[model.selectedLineIndex].length;
					}
					break;
				}
				case Keyboard.RIGHT:
				{
					var lineLength:int = model.lines[model.selectedLineIndex].length;
					if (model.hasSelection)
					{
						if (model.selectedLineIndex < model.selectionStartLineIndex)
						{
							model.caretIndex = model.selectionStartCharIndex;
							model.selectedLineIndex = model.selectionStartLineIndex;
						}
						removeSelection(); 
					}
					else if (model.caretIndex < lineLength)
					{
						model.caretIndex++;
					}
					else
					{
						if (model.selectedLineIndex >= model.lines.length) return;
						
						model.selectedLineIndex++;
						model.caretIndex = 0;
					}
					break;
				}
				case Keyboard.UP:
				{
					if (model.hasSelection) removeSelection();					
					if (model.selectedLineIndex == 0) return;
					
					model.selectedLineIndex--;
					if (model.caretIndex > model.selectedLine.length)
					{
						model.caretIndex = model.selectedLine.length;
					}
					break;
				}
				case Keyboard.DOWN:
				{
					if (model.hasSelection) removeSelection();
					if (model.selectedLineIndex >= model.lines.length) return;
										
					model.selectedLineIndex++;
					if (model.caretIndex > model.selectedLine.length)
					{
						model.caretIndex = model.selectedLine.length;
					}
					break;
				}
			}
			editor.invalidateSelection();
		}
		
		public function removeSelection():void
		{
			model.selectionStartCharIndex = -1;
			model.selectionStartLineIndex = -1;
		}
		
		private function getRendererAtPoint(x:int, y:int):TextLineRenderer
		{
			for each (var rdr:TextLineRenderer in model.itemRenderersInUse)
			{
				if (rdr.getRect(editor.itemContainer).contains(x, y))
				{
					return rdr;
				}
			}
			
			return null;
		}
		
	}
}